﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System.Runtime.Serialization;
using System.Text;
using System.Xml.Serialization;
using System;
using System.Threading;
using System.ComponentModel;
using System.Windows;
using System.Collections;
using System.Collections.Generic;
using BrainTechLLC.ThreadSafeObjects;
using System.Collections.ObjectModel;
#if USE_HYPER
using Hyper.ComponentModel;
#endif

namespace BrainTechLLC
{
    public partial class GameChar : GameThingBaseClass, IKeywordAccessible, IGameThing, IChangeable,
        INotifiable, ICanBeNotified, IHasPropertyData, ICanBePlacedInWorld, IHasLocationInt, IHasNameAndDescription,
        IRaisesNotifications, ICanReceiveCommands, INotifyPropertyChanged,
        IViewableThing, ICanObserveViewable, IEventPerceiver, INotifyPropertyChanging
    {
        [field: NonSerialized]
        public virtual event EventHandler<ObjectEventArgs<INotificationMessage>> NotificationRaised;

        [DataMember]
        public StateCollection _states;

        //  [DataMember]
        [NonSerialized]
        public InfluenceCollection _influenceCollection;

        [DataMember]
        public LocationInt _locationInt;

        [DataMember]
        public AbilityCollection _abilities;

#if NO_SILVERLIGHT
        [Browsable(true)]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public override StateCollection States
        {
            get
            {
                if (_states == null)
                    Interlocked.CompareExchange<StateCollection>(ref _states, new StateCollection() { AssociatedWith = AssociatedID }, null);

                return _states;
            }
            set
            {
                if (!_states.AreEqual(value))
                {
                    OnPropertyChanging("States", _states, value);
                    _states = value;
                    OnPropertyChanged("States", _states, value);
                }
            }
        }

        ~GameChar()
        {
        }


        public override ObservableCollection<Ability> ObservableAbilities
        {
            get
            {
                return (_abilities == null) ? new ObservableCollection<Ability>() :
                    Abilities.Find<Ability>().ToObservable();
            }
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        public AbilityCollection Abilities
        {
            get
            {
                if (_abilities == null)
                    Interlocked.CompareExchange<AbilityCollection>(ref _abilities, new AbilityCollection(), null);

                return _abilities;
            }
        }

        public void SendLocationInt(LocationInt loc, long location)
        {
            if (NotificationRaised != null)
            {
                StringMessage msg = new StringMessage() { ID = AssociatedID, String1 = "LocationInt", String2 = loc.ToString(), String3 = location.ToString() };
                Notify(new Notification(msg));
            }
        }

        public void SetLocationInt(LocationInt loc, long location)
        {
            LocationInt = loc;
            SendLocationInt(loc, location);
        }

#if NO_SILVERLIGHT
        [Browsable(true)]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        [Category("World")]
        public LocationInt LocationInt
        {
            get
            {
                if (_locationInt == null)
                    Interlocked.CompareExchange<LocationInt>(ref _locationInt, new LocationInt(), null);

                return _locationInt;
            }
            set
            {
                if (!_locationInt.AreEqual(value))
                {
                    GameLocation loc = WorldMap.Instance.World[value.x, value.y, value.z];
                    
                    if (loc != null)
                    {
                        Location = loc.AssociatedID;
                    }

                    OnPropertyChanging("LocationInt", _locationInt, value);
                    _locationInt = value;
                    OnPropertyChanged("LocationInt", _locationInt, value);
                }
            }
        }

        [NonSerialized, XmlIgnore]
        public AssociatedIDCollection _attackers;

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [Category("Temporary")]
        [XmlIgnore]
        public AssociatedIDCollection Attackers
        {
            get
            {
                if (_attackers == null)
                    Interlocked.CompareExchange<AssociatedIDCollection>(ref _attackers, new AssociatedIDCollection(), null);

                return _attackers;
            }
            set
            {
                if (!_attackers.AreEqual(value))
                {
                    OnPropertyChanging("Attackers", _attackers, value);
                    _attackers = value;
                    OnPropertyChanged("Attackers", _attackers, value);
                }
            }
        }

        [DataMember]
        public ItemCollection _items;

        [XmlIgnore]
        public ItemCollection Items
        {
            get
            {
                if (_items == null)
                    Interlocked.CompareExchange<ItemCollection>(ref _items, new ItemCollection(), null);

                return _items;
            }
            set
            {
                if (!_items.AreEqual(value))
                {
                    OnPropertyChanging("Items", _items, value);
                    _items = value;
                    OnPropertyChanged("Items", _items, value);
                }
            }
        }

        [NonSerialized, XmlIgnore]
        public ThreadSafeQueue<INotificationMessage> _notifications;

#if NO_SILVERLIGHT
        [Browsable(true)]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        [Category("Misc")]
        public ThreadSafeQueue<INotificationMessage> Notifications
        {
            get
            {
                if (_notifications == null)
                    Interlocked.CompareExchange<ThreadSafeQueue<INotificationMessage>>(ref _notifications, new ThreadSafeQueue<INotificationMessage>(), null);

                return _notifications;
            }
            set
            {
                if (!_notifications.AreEqual(value))
                {
                    OnPropertyChanging("Notifications", _notifications, value);
                    _notifications = value;
                    OnPropertyChanged("Notifications", _notifications, value);
                }
            }
        }

        [NonSerialized, XmlIgnore]
        public SequenceOfModifications _changesAndActions;

#if NO_SILVERLIGHT
        [Browsable(true)]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        [Category("Misc")]
        public SequenceOfModifications ChangesAndActions
        {
            get
            {
                if (_changesAndActions == null)
                    Interlocked.CompareExchange<SequenceOfModifications>(ref _changesAndActions, new SequenceOfModifications(), null);

                return _changesAndActions;
            }
            set
            {
                if (!_changesAndActions.AreEqual(value))
                {
                    OnPropertyChanging("ChangesAndActions", _changesAndActions, value);
                    _changesAndActions = value;
                    OnPropertyChanged("ChangesAndActions", _changesAndActions, value);
                }
            }
        }
    }
}